package cntv.player.engine;

import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

import cntv.player.core.util.LogUtil;

import android.util.Log;

public class ThreadPool extends ThreadPoolExecutor {
	
	private static final String TAG = "ThreadPool";
	private static int corePoolSize;//核心线程，最小线程数
	private static int maxPoolSize;//最大线程数
	private static int queueCapacity;//工作队列长度
	private static BlockingQueue<Runnable> workQueue; // 工作队列
	private static long keepAliveTime = 3;// 线程空闲最长时间
	private static ThreadPool pool = null;
	static {
		corePoolSize = getCPUCores() == 1 ?  2 : getCPUCores();	//核心线程数等于当前系统的cpu核心数，至少维护2个核心线程 
		queueCapacity = corePoolSize * 2;//单核维护4个等待任务 
		maxPoolSize = corePoolSize + 4;//维护4个应急线程
	}
	/**
	 * @param corePoolSize 池中所保存的线程数，包括空闲线程
	 * @param maximumPoolSize 池中允许的最大线程数
	 * @param keepAliveTime 当线程数大于corePoolSize核心线程时，此为终止前多余的空闲线程等待新任务的最长时间
	 * @param unit 参数的时间单位
	 * @param workQueue 执行前用于保持任务的队列,此队列仅保持由 execute方法提交的 Runnable任务
	 * @param handler 超出线程范围和队列容量而使执行被阻塞时所使用的处理程序
	 */
	private ThreadPool(int corePoolSize, int maximumPoolSize,long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,handler);
	}
	
	/**
	 * 获取线程池实例，
	 * @return
	 */
	public static synchronized ThreadPool getInstance() {
		if (pool == null) {
			workQueue=new ArrayBlockingQueue<Runnable>(queueCapacity);
			pool = new ThreadPool(corePoolSize, maxPoolSize, keepAliveTime,TimeUnit.SECONDS, workQueue,new ThreadPoolExecutor.CallerRunsPolicy());
		}
		return pool;
	}
	
	
	
	@Override
	protected void beforeExecute(Thread t, Runnable r) {
		// TODO Auto-generated method stub
		super.beforeExecute(t, r);
//		LogUtil.i("zl", "ThreadPool beforeExecute() Thread name = " + t.getName());
	}
	
	@Override
	protected void afterExecute(Runnable r, Throwable t) {
		// TODO Auto-generated method stub
		super.afterExecute(r, t);
		
	}
	
	
	/**
	 * 获取CPU核心数
	 * @return
	 */
	private static int getCPUCores() {
	    //Private Class to display only CPU devices in the directory listing
	    class CpuFilter implements FileFilter {
	        @Override
	        public boolean accept(File pathname) {
	            //Check if filename is "cpu", followed by a single digit number
	            if(Pattern.matches("cpu[0-9]", pathname.getName())) {
	                return true;
	            }
	            return false;
	        }      
	    }
	    try {
	        //Get directory containing CPU info
	        File dir = new File("/sys/devices/system/cpu/");
	        //Filter to only list the devices we care about
	        File[] files = dir.listFiles(new CpuFilter());
//	        Log.d(TAG, "CPU Count: "+files.length);
	        //Return the number of cores (virtual CPU devices)
	        return files.length;
	    } catch(Exception e) {
	        //Print exception
	        Log.d(TAG, "CPU Count: Failed.");
	        e.printStackTrace();
	        //Default to return 1 core
	        return 1;
	    }
	}
}
